#!/bin/bash

# ********************************************************************************************************************
#
# El propósito de este comando es leer los archivos que se encuentran en el directorio $ACEPDIR y grabar sus registros
# formateados en archivos de préstamos por país.
#       - Es el tercero en orden de ejecución
#       - Este comando puede ser disparado manualmente o a través del comando DetectaY
#       - Graba en su archivo de Log
#
# ********************************************************************************************************************

# Pre: -
# Post: Se cargan las variables  para las rutas de archivos
function cargarVariables(){
	config="../conf/InstalY.conf"
	export CONFIG=$config
	
	path_acepdir=$(grep '^ACEPDIR' $CONFIG | cut -f2 -d'=')
	export ACEPDIR=$path_acepdir

	path_rechdir=$(grep '^RECHDIR' $CONFIG | cut -f2 -d'=')
	export RECHDIR=$path_rechdir

	path_procdir=$(grep '^PROCDIR' $CONFIG | cut -f2 -d'=')
	export PROCDIR=$path_procdir

	path_confdir=$(grep '^CONFDIR' $CONFIG | cut -f2 -d'=')
	export CONFDIR=$path_confdir

	path_logdir=$(grep '^LOGDIR' $CONFIG | cut -f2 -d'=')
	export LOGDIR=$path_logdir

	logext=$(grep '^LOGEXT' $CONFIG | cut -f2 -d'=')
	export LOGEXT=$logext
	
	path_acepdir="$path_acepdir/"
	path_rechdir="$path_rechdir/"
	path_log="$path_logdir/Interprete.$logext"
	path_prestamo="$path_procdir/PRESTAMO."
	archT1="$path_confdir/T1.tab"
	archT2="$path_confdir/T2.tab"  
}

# Pre: -
# Post: Se inicializa el log del interprete
function iniciarLog(){  	        
	declare local cantidadArchivos=`ls $path_acepdir | wc -l`
        loguear "*********************************************************"
        loguear "Inicio de Interprete PID= $$ "
        loguear "Hay $cantidadArchivos archivo/s de entrada"
}

# Pre: $1 archAcepdir
# Post: Se retorna verdadero si archAcepdir esta duplicado.
function estaArchivoAcepdirDuplicado(){
        estaDuplicado=$FALSE
        declare local listaProcdir=`ls $path_procdir`   
        for archProcdir in $listaProcdir
        do
                if [ $1 == $archProcdir ]       
                then
                        estaDuplicado=$TRUE
                fi
        done
}

# Pre: $1 archAcepdir duplicado
# Post: Se procesa el registro duplicado de manera que se loguea esta circunstancia y se mueve
# el mismo a la carpeta de rechazados.
function procesarDuplicado(){
	loguearAdvertencia "ARCHIVO DUPLICADO: $1"

        #calculo la cantidad de registros de entrada
        while read regAcepdir
        do
                let cantRegInput=$cantRegInput+1
        done < $path_acepdir$1

        ./MoverY.sh $path_acepdir$1 $path_rechdir
}

# Pre: $1 clave
# Post: Se obtienen los separadores de la tabla 1.
function obtenerSeparadorTabla1(){
        formatosTabla1Hallados=$FALSE
        if [ -r $archT1 ] 
        then            
                declare local regT1=`grep ^$1 $archT1`
                declare local cantidadElementosRegT1=${#regT1[@]}
                if [ $cantidadElementosRegT1 -eq 1 ]
                then
                        SEP_CAMP_T1=`echo $regT1 | cut -f3 -d'-'`
                        SEP_DEC_T1=`echo $regT1 | cut -f4 -d'-'`
                        formatosTabla1Hallados=$TRUE
                else
                        loguearError "NO SE ENCONTRO FORMATO EN TABLA1 CORRESPONDIENTE A LA CLAVE $1"
                fi
        else
  	        loguearError "NO EXISTE O NO SE TIENE ACCESO AL ARCHIVO $archT1"
        fi
}

# Pre: $1 clave a buscar
# Post: Se obtienen los formatos especificados en la tabla 2. 
function obtenerFormatoCamposTabla2(){
        formatosTabla2Hallados=$FALSE
	if [ -r $archT2 ] 
        then    
		declare local validarCampos=$TRUE
		unset vector
                vector=()  # creo un vector para almacenar los campos en orden ascendente
		declare local IFS='
'
                declare local listaT2=`grep ^$1 $archT2`
                for regT2 in $listaT2
                do       	
                        NOMB_CAMP=`echo $regT2 | cut -f3 -d'-'` 
                        ORD_CAMP=`echo $regT2 | cut -f4 -d'-'` 
                        FMT_CAMP=`echo $regT2 | cut -f5 -d'-'`		
			vector[$ORD_CAMP]=$NOMB_CAMP-$FMT_CAMP
			declare local testNOM_CAMP=`echo $NOMB_CAMP | grep "^.*$"`
			declare local testORD_CAMP=`echo $ORD_CAMP | grep "^[0-9]*$"`
			declare local testFMT_CAMP=`echo $FMT_CAMP | grep "^.*$"`
			if [ ${#testNOM_CAMP} -eq 0 ] || [ ${#testORD_CAMP} -eq 0 ] || [ ${#testFMT_CAMP} -eq 0 ];
			then
				validarCampos=$FALSE	
		                loguearError "ESPECIFICACION DE CAMPO INVALIDA EN TABLA 2: NOMBRE=$NOMB_CAMP , ORDEN= $ORD_CAMP , FORMATO= $FMT_CAMP"
			fi
                done    
                formatosTabla2Hallados=$validarCampos
        else
                loguearError "NO EXISTE O NO SE TIENE ACCESO AL ARCHIVO $archT2"
        fi

}

# Pre: $1 archAcepdir (cada archivo es de un país y un sistema dado)
# Post: Procesa el archivo aceptado y luego lo graba en el archivo de salida.
function procesarArchivoAceptado(){
        loguear "ARCHIVO PROCESADO: $1"

        declare local IFS="$SEP_CAMP_T1"
	numeroDeLinea=0 # numero de linea del registro que se esta procesando
        while read regAcepdir
        do
		declare local camposProcedadosCorrectamente=$TRUE  # indica si todos los campos del registro son correctos

		# inicializo las variables de montos del archivo de salida
		inicializarVariablesDeMontos
		let numeroDeLinea=$numeroDeLinea+1
                i=0  # indice del vector
                for valorCampo in $regAcepdir
                do
			let i=$i+1
                        nombreCampo=`echo ${vector[i]} | cut -f1 -d'-'` 
                        formatoCampo=`echo ${vector[i]} | cut -f2 -d'-'`
                        procesarCampo $valorCampo $nombreCampo $formatoCampo $numeroDeLinea
			campoProcesado=$?
			if [ "$campoProcesado" == "$FALSE" ]
			then
				camposProcedadosCorrectamente=$FALSE
			fi
                done

		# aumento el contador de registros de input
		let cantRegInput=$cantRegInput+1

		# corroboro que todos los campos se hayan procesado correctamente
		if [ "$camposProcedadosCorrectamente" == "$TRUE" ]
		then	        
			# corroboro que existan el codigo de prestamo
			if [ "$PRES_ID" != "" ]
			then
				# calculo el valor del monto restante                       
				MT_REST=`echo "scale=2; $pres+$impago+$inde+$innode-$deb" | bc`

				declare local parteEntera=`echo $MT_REST | cut -f1 -d'.'`                        
				declare local parteDecimal=`echo $MT_REST | cut -f2 -d'.'`
				if [ "$parteEntera" == "" ]
				then
					parteEntera=0                       
				fi

				MT_REST=$parteEntera","$parteDecimal

				# si el monto restante es menor a cero no se graba
				if [ "${MT_REST[@]:0:1}" == "-" ]
				then
					loguearAdvertencia "--> Linea $numeroDeLinea: El registro tiene un monto restante menor a 0 (no se graba)"
				else
			        	# grabo el registro en el archivo de salida
			        	grabarRegistro
				fi
			else
				loguearError "--> Linea $numeroDeLinea: No tiene codigo de prestamo."
			fi
		else
			loguearError "--> Linea $numeroDeLinea: No todos los campos fueron procesados correctamente."
		fi
        done < $path_acepdir$1
}     

# Pre: -
# Post: Inicializa las variables de monto del archivo de salida
function inicializarVariablesDeMontos(){
	PRES_CLI=""
	PRES_CLI_ID=""
	PRES_ID=""
	MT_PRES=0
	MT_IMPAGO=0
	MT_INDE=0
	MT_INNODE=0
	MT_DEB=0
	MT_REST=0
	pres=0
	impago=0
	inde=0
	innode=0
	deb=0
	rest=0
}  

# Pre: $1 valorCampo - $2 nombreCampo - $3 formatoCampo - $4 numeroDeLinea
# Post: Redirige a distintas funciones dependiendo del formato del campo
# Nota: Las variables se convierten al formato estandar.
function procesarCampo(){
	declare local IFS='
'    		
	declare local retorno=$TRUE

        case $2 in
        "MT_IMPAGO" | "MT_PRES" | "MT_DEB" | "MT_INDE" | "MT_INNODE")
		determinarCampoNumerico $1 $2 $3 $4
		retorno=$?
                ;;
        "PRES_CLI" | "CTB_ESTADO" | "PRES_ID" | "PRES_CLI_ID")
		determinarCampoAlfanumerico $1 $2 $3 $4
		retorno=$?
                ;;
        "CTB_FE")
		determinarCampoFecha $1 $3 $4
		retorno=$?
                ;;
        esac 
	return $retorno   
}  

# Pre: $1 valor $2 formato $3 linea
# Post: Se obtienen los campos de la fecha.
# RETURNS: $TRUE si no ocurrio ningun problema y $FALSE si la fecha o el formato no es válido.
function determinarCampoFecha(){
        declare local retorno=$TRUE     
        case $2 in
        "ddmmyy8.")
                if [ ${#1} -eq 8 ] 
                then 
			CTB_DIA=`echo $1 | cut -c1-2`
			CTB_MES=`echo $1 | cut -c3-4`
                        CTB_ANIO=`echo $1 | cut -c5-8`
                        validarFecha $CTB_DIA $CTB_MES $CTB_ANIO $3
			retorno=$?
                else	
			loguearError "--> Linea $3: LA FECHA NO CUMPLE EL FORMATO $2 : $1"
                        retorno=$FALSE
                fi
                ;;
        "ddmmyy10.")
                if [ ${#1} -eq 10 ] 
                then 
                        CTB_DIA=`echo $1 | cut -c1-2`
                        CTB_MES=`echo $1 | cut -c4-5`
                        CTB_ANIO=`echo $1 | cut -c7-10`
                        validarFecha $CTB_DIA $CTB_MES $CTB_ANIO $3
			retorno=$?
                else
			loguearError "--> Linea $3: LA FECHA NO CUMPLE EL FORMATO $2 : $1"
                        retorno=$FALSE
                fi
                ;;
        "yymmdd8.")
                if [ ${#1} -eq 8 ] 
                then 
                        CTB_DIA=`echo $1 | cut -c7-8`
                        CTB_MES=`echo $1 | cut -c5-6`
                        CTB_ANIO=`echo $1 | cut -c1-4`
                        validarFecha $CTB_DIA $CTB_MES $CTB_ANIO $3
			retorno=$?
                else
                       	loguearError "--> Linea $3: LA FECHA NO CUMPLE EL FORMATO $2 : $1"
                        retorno=$FALSE
                fi
                ;;
        "yymmdd10.")
                if [ ${#1} -eq 10 ] 
                then 
                        CTB_DIA=`echo $1 | cut -c9-10`
                        CTB_MES=`echo $1 | cut -c6-7`
                        CTB_ANIO=`echo $1 | cut -c1-4`
                        validarFecha $CTB_DIA $CTB_MES $CTB_ANIO $3
			retorno=$?
                else
                       	loguearError "--> Linea $3: LA FECHA NO CUMPLE EL FORMATO $2 : $1"
                        retorno=$FALSE
                fi
                ;;
        *) #default
                CTB_ANIO="0000"
                CTB_MES="01"
                CTB_DIA="01"
		loguearError "--> Linea $3: FORMATO DE FECHA NO PERMITIDO : $2 "
                retorno=$FALSE
                ;;
        esac
	return $retorno
}

# Pre: Los parametros $1 $2 y $3 son el día, el mes y el año de una fecha a valir dada. $4 linea
# Post: Se retorna $TRUE si cumple con ser una fecha válida, $FALSE caso contrario.
function validarFecha(){
        declare local let retorno=$TRUE
        declare local testANIO=`echo $3 | grep '^[0-9][0-9][0-9][0-9]'`
        declare local testMES=`echo $2 | grep "\(^[1][0-2]\)\|\(^[0][1-9]\)"`   
        declare local testDIA=`echo $1 | grep "\(^[0][1-9]\)\|\(^[1-2][0-9]\)\|\(^[3][0-1]\)"`
	if [ ${#testANIO} -eq 0 ] || [ ${#testMES} -eq 0 ] || [ ${#testDIA} -eq 0 ] || [ ${#testANIO} -ge 5 ] || [ ${#testMES} -ge 3 ] || [ ${#testDIA} -ge 3 ];
        then
		retorno=$FALSE
                loguearError "--> Linea $4: FECHA INVÁLIDA: $1/$2/$3"
        fi      
        return $retorno                            
}

# Pre: $1 valorCampo - $2 nombreCampo - $3 formatoCampo - $4 numeroDeLinea
# Post: Se retorna $TRUE si se cumplen todas estas condiciones:
#  1) el formato especificado es valido
#  2) el valor se ajusta a dicho formato
# En caso contrario se retorna $FALSE
function determinarCampoAlfanumerico(){
	declare local retorno=$TRUE
	declare local aux=`echo $3 | grep '^\$[1-9][0-9]*\.$'`
	if [ ${#aux} -ge 3 ]
	then
		declare local fin=${#3}
		let fin=$fin-1
		declare local longitud=`echo $3 | cut -c2-$fin`
		
		# verifico que la longitud del valor sea menor o igual a la permitida segun el formato
		if [ ${#1} -le $longitud ]
		then
			case $2 in
		 		"PRES_CLI")
			                PRES_CLI=$1
		                ;;
			        "CTB_ESTADO")
                			CTB_ESTADO=$1
		                ;;
			        "PRES_ID")
			                PRES_ID=$1
		                ;;
			        "PRES_CLI_ID")
			                PRES_CLI_ID=$1
		                ;;
			esac    
		else
			loguearError "--> Linea $4: EL VALOR $1 NO CUMPLE EL FORMATO : $3 "			
		fi
	else
		loguearError "--> Linea $4: FORMATO ALFANUMERICO NO PERMITIDO : $3"
	fi
	return $retorno 
}

# Pre: $1 valorCampo - $2 nombreCampo - $3 formatoCampo - $4 numeroDeLinea
# Post: Se retorna $TRUE si se cumplen todas estas condiciones:
#  1) el formato especificado es valido
#  2) el valor se ajusta a dicho formato
# En caso contrario se retorna $FALSE
function determinarCampoNumerico(){
	declare local retorno=$TRUE
        declare local aux=`echo $3 | grep '^commax[1-9][0-9]*\.[1-9][0-9]*$'`
        if [ ${#aux} -ge 9 ]
        then    
                declare local cantEnteros=`echo $aux | cut -f1 -d'.'`
                declare local cantDecimales=`echo $aux | cut -f2 -d'.'`
                cantEnteros=`echo $cantEnteros | cut -c7-${#cantEnteros}`
		if [ $cantEnteros -ge 1 ] && [ $cantDecimales -ge 1 ];
                then
			declare local entero=`echo $1 | grep "^[0-9]*$"`
			declare local decimal=`echo $1 | grep "^[0-9]*[$SEP_DEC_T1][0-9]*$"`
			if [ ${#entero} -ge 1 ] || [ ${#decimal} -ge 1 ]
			then	 
				declare local IFS='
'        			
				declare local aux1=0
				declare local aux2=0
				if [ ${#entero} -ge 1 ]
				then
					aux1=$entero",00"
					aux2=$entero".00"		
					if [ ${#entero} -gt $cantEnteros ]					
					then
						retorno=$FALSE
						loguearError "--> Linea $4: EL VALOR NO CUMPLE EL FORMATO $3 : $1"	
					fi
				elif [ ${#decimal} -ge 1 ]
				then
					declare local parteDecimal=`echo $decimal | cut -f2 -d$SEP_DEC_T1`
					declare local parteEntera=`echo $decimal | cut -f1 -d$SEP_DEC_T1`
					aux1=$parteEntera","$parteDecimal
					aux2=$parteEntera"."$parteDecimal
					if [  ${#parteEntera} -gt $cantEnteros ]
					then
						retorno=$FALSE
						loguearError "--> Linea $4: EL VALOR NO CUMPLE EL FORMATO $3 : $1"	
					elif [  ${#parteDecimal} -gt $cantDecimales ]					
					then
						retorno=$FALSE
						loguearError "--> Linea $4: EL VALOR NO CUMPLE EL FORMATO $3 : $1"	
					fi
				fi
				case $2 in
					"MT_IMPAGO")
						MT_IMPAGO=$aux1
						impago=$aux2
						;;
					"MT_PRES")
						MT_PRES=$aux1
						pres=$aux2
						;;
					"MT_DEB")       
						MT_DEB=$aux1
						deb=$aux2
						;;
					"MT_INDE")
						MT_INDE=$aux1
						inde=$aux2
						;;
					"MT_INNODE")
						MT_INNODE=$aux1
						innode=$aux2
						;;
				esac    
			else				
				loguearError "--> Linea $4: EL VALOR NO CUMPLE EL FORMATO $3 : $1"
	                        retorno=$FALSE
			fi
                else
			loguearError "--> Linea $4: EL VALOR NO CUMPLE EL FORMATO $3 : $1"
                        retorno=$FALSE
                fi
        else
		loguearError "--> Linea $4: FORMATO NUMERICO NO PERMITIDO : $3"
                retorno=$FALSE  
        fi
        return $retorno 
}

# Pre: El registro ya se proceso y esta listo para ser grabado.
# Post: Graba en el archivo de salida.
function grabarRegistro(){
	#aumento el contador de registros de output
        let cantRegOutput=$cantRegOutput+1

        PAIS_ID=`echo $archAcepdir | cut -f1 -d'-'`
        SIS_ID=`echo $archAcepdir | cut -f2 -d'-'`

	DIA=$(date +"%d")
	MES=$(date +"%m")
	ANIO=$(date +"%Y")
	INS_FE=`echo $DIA'/'$MES'/'$ANIO`

	INS_USER=$LOGNAME
	local IFS='
'
        path_salida=$path_prestamo$PAIS_ID
	    echo $SIS_ID';'$CTB_ANIO';'$CTB_MES';'$CTB_DIA';'$CTB_ESTADO';'$PRES_ID';'$MT_PRES';'$MT_IMPAGO';'$MT_INDE';'$MT_INNODE';'$MT_DEB';'$MT_REST';'$PRES_CLI_ID';'$PRES_CLI';'$INS_FE';'$INS_USER >> $path_salida
}

# Pre: -
# Post: Se finaliza el log del interprete
function finalizarLog(){
	loguear "Cantidad de registros de input: $cantRegInput"
	loguear "Cantidad de registros de output: $cantRegOutput"
	loguear "Fin de Interprete PID= $$"
	loguear "*********************************************************"
}


# Pre: $1 Mensaje
# Post: Se loguea mensaje informativo.
function loguear(){
	./GlogY.sh Interprete I "$1"
}

# Pre: $1 Mensaje
# Post: Se loguea mensaje de error.
function loguearError(){
	./GlogY.sh Interprete E "      $1"
}

# Pre: $1 Mensaje
# Post: Se loguea mensaje de error.
function loguearAdvertencia(){
	./GlogY.sh Interprete W "$1"
}


# ---------------------------------------------------------------------------------------------------
# Sección Principal de Interprete
# ---------------------------------------------------------------------------------------------------

export TRUE=1
export FALSE=0

cantRegInput=0
cantRegOutput=0

# Se cargan las variables  para las rutas de archivos
cargarVariables

# Inicializacion de archivo de log
iniciarLog

# Recorro todos los archivos de ACEPDIR para procesarlos
listaAcepdir=`ls $path_acepdir`
for archAcepdir in $listaAcepdir
do    
        #verifico que no sea un archivo duplicado
        estaArchivoAcepdirDuplicado $archAcepdir
        if [ "$estaDuplicado" == "$TRUE" ]  
        then    
                procesarDuplicado $archAcepdir
        else
                
                # el archivo no esta duplicado por lo tanto hay que procesarlo
                # obtenemos la clave para acceder a la tabla 1 y 2
                clave=`echo $archAcepdir | cut -f1,2 -d'-'`
        
                # obtenemos los separadores de la tabla 1
                obtenerSeparadorTabla1 $clave   
        
                # obtenemos los campos de la tabla 2
                obtenerFormatoCamposTabla2 $clave

                # si se hallaron los formatos correctamente se procesa el archivo
                if [ "$formatosTabla1Hallados" == "$TRUE" ] && [ "$formatosTabla2Hallados" == "$TRUE" ]
                then 
                        procesarArchivoAceptado $archAcepdir
		fi
                
                # muevo el archivo a la carpeta de procesados
                ./MoverY.sh $path_acepdir$archAcepdir $path_procdir

        fi # fin de procesar un archivo

done # fin de procesar todos los archivos

# Finalizacion de archivo de log
finalizarLog

exit 0

